/*
============================================================================
 Name        : ScreenCapture.cpp
 Author      : DANG Zhengfa
 Version     :
 Copyright   : Zhengfa Company Limited
 Description : CScreenCapture implementation
============================================================================
*/

#include "ScreenCapture.h"
#include "Utilities.h"  // For GetUniqueImagePath
#include "Log.h"  // For PrintString16, PrintNumber

#include <LockServer.rsg>  // to load string resource

#include <w32std.h>      // For RWsSession,CWsScreenDevice,RWindowGroup, ws32.lib 
#include <fbs.h>   // For CFbsBitmap, fbscli.lib
#include <AknGlobalNote.h>  // For CAknGlobalNote,Link against: aknnotify.lib eiksrv.lib 
#include <ImageConversion.h>   // For CImageEncoder, ImageConversion.lib
#include <barsc.h>  // for RResourceFile,Link against: bafl.lib 
#include <barsread.h>  // for TResourceReader, Link against: bafl.lib 


_LIT8(KJEPGMIMEType,"image/jpeg");
_LIT(KLockServerCaptureSucc,"Screen Capture Success!");
_LIT(KLockServerCaptureFail,"Screen Capture Fail!");
_LIT(KResourceFilename, "LockServer.rsc");


CScreenCapture::CScreenCapture() : CActive(EPriorityStandard)	// Standard priority
{
}

void CScreenCapture::ConstructL()
{
	User::LeaveIfError(iRF.Connect());	// Initialize RF session
	CActiveScheduler::Add(this);				// Add to scheduler
	
	TRAPD(err, LoadStringL());
	if( err != KErrNone )
	{
		// error happens, 
		PrintNumber(err);
		// make sure text has a value
		if( !iTextFail )
			iTextFail = KLockServerCaptureFail().AllocL();
		if( !iTextSuccess )
			iTextSuccess = KLockServerCaptureSucc().AllocL();
	}

	iBitmap = NULL;
	iEncoder = NULL;
	iFrameImageData = NULL;
}

CScreenCapture::~CScreenCapture()
{
	Cancel(); // Cancel any request, if outstanding
	// Delete instance variables if any
	
	iRF.Close();
	
	// clean up
	if(iBitmap)
	{
		delete iBitmap;
		iBitmap = NULL;
	}

	if(iFrameImageData)
	{
		delete iFrameImageData;
		iFrameImageData = NULL;
	}
	if(iEncoder)
	{
		delete iEncoder;
		iEncoder = NULL;
	}
	delete iTextFail;
	delete iTextSuccess;
}

void CScreenCapture::DoCancel()
{
	if(iEncoder)
		iEncoder->Cancel();
}

void CScreenCapture::StartCaptureL()
{
	// get screen information
	TSize screenSize = iScreen->SizeInPixels();
	TDisplayMode displayMode = iScreen->DisplayMode();
	PrintNumber(screenSize.iHeight);
	PrintNumber(screenSize.iWidth);
	
	// create bitmap
	if(iBitmap) 
	{
		delete iBitmap;
		iBitmap = NULL;
	}
	iBitmap = new(ELeave)CFbsBitmap;
	PrintString16(_L("create bitmap success"));

	// capture screen to bitmap
	User::LeaveIfError(iBitmap->Create(screenSize, displayMode));
	iScreen->CopyScreenToBitmap(iBitmap);
	PrintString16(_L("capture sucess"));

	// Get file name
	TFileName fname;
	GetUniqueImagePath(fname);
	PrintString16(fname);

	// create encoder
	iEncoder = CImageEncoder::FileNewL(iRF,fname,KJEPGMIMEType);
	PrintString16(_L("create encoder sucess"));

	// create jpeg image data
	TJpegImageData *imageData = new (ELeave) TJpegImageData;
	CleanupStack::PushL(imageData);
	// Set some format specific data
	imageData->iSampleScheme = TJpegImageData::EColor444;
	imageData->iQualityFactor = 95;

	// create frame image data
	iFrameImageData = CFrameImageData::NewL();
	// frameData - ownership passed to iFrameImageData after AppendImageData
	User::LeaveIfError(iFrameImageData->AppendImageData(imageData));
	CleanupStack::Pop(imageData);  // CFrameImageData takes owner of the data

	PrintString16(_L("create jpeg image data sucess"));

	// Do the convert
	iEncoder->Convert(&iStatus,*iBitmap,iFrameImageData);
	PrintString16(_L("begin to convert"));
}

void CScreenCapture::StartL()
{
	if( IsActive() )  // capture is ongoing.
	{
		PrintString16(_L("capture ongoing, return"));
		return;
	}
	
	// OK, we are going to display all image types supported by symbian
	TRAPD(err, StartCaptureL());
	if( err == KErrNone)
		SetActive();	// Tell scheduler a request is active
	else
		PrintNumber(err);

}

void CScreenCapture::RunL()
{
	PrintString16(_L("CScreenCapture::RunL"));
	// convert is finished, check the result
	if( iStatus == KErrNone )
	{
		PrintString16(_L("convert ok"));
		// show sucessful note
		CAknGlobalNote* globalNote = CAknGlobalNote::NewL();
		CleanupStack::PushL( globalNote );
		globalNote->ShowNoteL(EAknGlobalInformationNote, *iTextSuccess); 
		CleanupStack::PopAndDestroy(globalNote);
	}
	else
	{
		PrintString16(_L("convert failed"));
		// show failed note
		CAknGlobalNote* globalNote = CAknGlobalNote::NewL();
		CleanupStack::PushL( globalNote );
		globalNote->ShowNoteL(EAknGlobalErrorNote, *iTextFail); 
		CleanupStack::PopAndDestroy(globalNote);
	}

	PrintString16(_L("CScreenCapture, cleanup"));
	// cleanup
	if(iBitmap)
	{
		delete iBitmap;
		iBitmap = NULL;
	}

	if(iFrameImageData)
	{
		delete iFrameImageData;
		iFrameImageData = NULL;
	}
	if(iEncoder)
	{
		delete iEncoder;
		iEncoder = NULL;
	}
}

void CScreenCapture::LoadStringL()
{
	// first of all, get resource file name
#if !defined(__WINS__) // for WINS, logfile will be created in C:. Otherwise, in the same dir of exe
		TFileName rscFileName;
		GetProcessPath(rscFileName);
		rscFileName.Append(_L("\\"));
		rscFileName.Append(KResourceFilename);
#else
		TFileName rscFileName(_L("C:\\"));
		rscFileName.Append(KResourceFilename);
#endif
	
	PrintString16(rscFileName);

	// now to read string resource
	RResourceFile resourceFile;
	resourceFile.OpenL(iRF,rscFileName);
	CleanupClosePushL(resourceFile);   // push resourceFile

	TResourceReader theReader;
	HBufC8* dataBuffer;

	// read success text
	dataBuffer = resourceFile.AllocReadLC(R_TESTEXT_CAPTURE_SUCCESS);
	theReader.SetBuffer(dataBuffer);
	iTextSuccess = theReader.ReadTPtrC().AllocL();
	CleanupStack::PopAndDestroy(dataBuffer);
	
	PrintString16(*iTextSuccess);
	
	// read fail text
	dataBuffer = resourceFile.AllocReadLC(R_TESTEXT_CAPTURE_FAIL);
	theReader.SetBuffer(dataBuffer);
	iTextFail = theReader.ReadTPtrC().AllocL();
	CleanupStack::PopAndDestroy(dataBuffer);

	PrintString16(*iTextFail);

	// clean resourceFile
	CleanupStack::PopAndDestroy();  // pop resourceFile
}
void CScreenCapture::SetScreenDevice(CWsScreenDevice* aScreen)
{
	iScreen = aScreen;
}

